use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub input_path: PathBuf,
    pub generator: String,
    pub log_level: String,
    /// 项目根目录，用于确定主 xmake.lua 的位置
    /// 如果为 None，则使用当前工作目录
    #[serde(default)]
    pub project_root: Option<PathBuf>,
    /// 环境变量映射配置
    #[serde(default)]
    pub environment_variables: EnvironmentVariablesConfig,
    /// 迁移前需要运行的脚本配置
    #[serde(default)]
    pub pre_migration_scripts: PreMigrationScripts,
    /// 代码风格配置文件生成选项
    #[serde(default)]
    pub code_style: CodeStyleConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnvironmentVariablesConfig {
    /// 显式的环境变量映射（最高优先级）
    #[serde(default)]
    pub mappings: HashMap<String, String>,
    /// 是否启用系统环境变量查找
    #[serde(default = "default_true")]
    pub use_system_env: bool,
}

/// 迁移前脚本配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PreMigrationScripts {
    /// 脚本文件路径列表（支持相对路径和绝对路径）
    #[serde(default)]
    pub scripts: Vec<PathBuf>,
    /// 脚本工作目录（如果为 None，使用脚本所在目录）
    #[serde(default)]
    pub working_directory: Option<PathBuf>,
    /// 是否在脚本执行失败时继续（默认为 false，即失败时中止）
    #[serde(default)]
    pub continue_on_error: bool,
}

/// 代码风格配置文件生成选项
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CodeStyleConfig {
    /// 是否生成 .clang-format 文件（默认为 true）
    #[serde(default = "default_true")]
    pub generate_clang_format: bool,
    /// 是否生成 .clang-tidy 文件（默认为 true）
    #[serde(default = "default_true")]
    pub generate_clang_tidy: bool,
}


fn default_true() -> bool {
    true
}

impl Default for EnvironmentVariablesConfig {
    fn default() -> Self {
        Self {
            mappings: HashMap::new(),
            use_system_env: true,
        }
    }
}

impl Default for PreMigrationScripts {
    fn default() -> Self {
        Self {
            scripts: Vec::new(),
            working_directory: None,
            continue_on_error: false,
        }
    }
}

impl Default for CodeStyleConfig {
    fn default() -> Self {
        Self {
            generate_clang_format: true,
            generate_clang_tidy: true,
        }
    }
}



impl Default for Config {
    fn default() -> Self {
        Self {
            input_path: PathBuf::from("."),
            generator: "xmake".to_string(),
            log_level: "info".to_string(),
            project_root: None,
            environment_variables: EnvironmentVariablesConfig::default(),
            pre_migration_scripts: PreMigrationScripts::default(),
            code_style: CodeStyleConfig::default(),
        }
    }
}

impl Config {
    pub fn from_file(path: &PathBuf) -> crate::Result<Self> {
        let content = std::fs::read_to_string(path)?;
        let ext = path
            .extension()
            .and_then(|s| s.to_str())
            .map(|s| s.to_ascii_lowercase());

        // 只支持 TOML 格式
        match ext.as_deref() {
            Some("toml") => Ok(toml::from_str(&content)?),
            _ => {
                // 对于无扩展名或其他扩展名，尝试按 TOML 解析
                Ok(toml::from_str(&content)?)
            }
        }
    }

    pub fn to_file(&self, path: &PathBuf) -> crate::Result<()> {
        // 只支持 TOML 格式输出
        let content = toml::to_string_pretty(self)
            .map_err(|e| crate::BuildMigrateError::Config(e.to_string()))?;
        std::fs::write(path, content)?;
        Ok(())
    }
}
